﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using AsmDependency.Core.Services;
using AsmDependency.Core.UserInterface;
using AsmDependency.Utility;

namespace AsmDependency.Core.AsmApplication
{
    public abstract class AsmDependencyApplication : Object, IServiceProvider, IAsmApplicationIdentity
    {
        private CApplicationWindow _appWindow;
        private ServiceContainer _serviceContainer;
        private CCommandLine _commandLine;
        private PreferencesService _prefService;
        //private ComponentGalleryService _componentGalleryService;
        private GlobalExceptionHandler _exceptionHandler;
        private EventHandler _startupHandler;
        private IDictionary _webLinks;
        private bool _webLinksLoaded;

        protected abstract CApplicationWindow CreateApplicationWindow();

        #region [=== CONSTRUCTOR ===] 
        protected AsmDependencyApplication(CCommandLine commandLine) {
            if (instance != null) {
                throw new InvalidOperationException();
            }
            instance = this;
            this._commandLine = commandLine;
        }
        #endregion

        #region [=== METHODS ===]

        public void Run()
        {
            try
            {
                this.InitializeApplication();
                this._appWindow = this.CreateApplicationWindow();
                this._appWindow.InitialActivated += new EventHandler(this.OnApplicationWindowActivated);
                this._appWindow.Closing += new CancelEventHandler(this.OnApplicationWindowClosing);
                bool flag = false; // (this.ApplicationType & ApplicationType.Workspace) != ApplicationType.Generic;
                //this._packageManager.LoadPackages(this.CreateApplicationPackage());
                if (flag)
                {
                    //this._toolboxService.LoadToolbox();
                    //this._languageManager.LoadDocumentLanguages();
                    //this._docTypeManager.LoadDocumentTypes();
                    //this._projectManager.LoadProjectTypes();
                }
                System.Windows.Forms.Application.Run(this._appWindow);
            }
            catch (Exception)
            {
            }
            finally
            {
                try
                {
                    this.CloseApplication();
                }
                catch (Exception)
                {
                }
            }
        }

        private void InitializeApplication()
        {
            ServiceCreatorCallback callback = new ServiceCreatorCallback(this.OnCreateService);
            this._serviceContainer = new ServiceContainer();
            this._serviceContainer.AddService(typeof(IAsmApplicationIdentity), this);
            this._exceptionHandler = new GlobalExceptionHandler(this._serviceContainer);
            this._exceptionHandler.Initialize();
            this._prefService = new PreferencesService(this._serviceContainer);
            this._prefService.Load(this._commandLine.Options.Contains("reset"));
            this._serviceContainer.AddService(typeof(IPreferencesService), this._prefService);
            this._serviceContainer.AddService(typeof(IComponentGalleryService), callback);
            //this._packageManager = new CPackageManager(this._serviceContainer);
            //this._serviceContainer.AddService(typeof(IPackageManager), this._packageManager);
            //this._serviceContainer.AddService(typeof(IPrintService), callback);
            //this._serviceContainer.AddService(typeof(IWebBrowsingService), callback);
            //this._serviceContainer.AddService(typeof(IComponentGalleryService), callback);
            //this._serviceContainer.AddService(typeof(IDataObjectMappingService), callback);
            //if ((this.ApplicationType & ApplicationType.Workspace) != ApplicationType.Generic)
            //{
            //    //this._projectManager = new ProjectManager(this._serviceContainer);
            //    //this._serviceContainer.AddService(typeof(IProjectManager), this._projectManager);
            //    //this._languageManager = new LanguageManager(this._serviceContainer);
            //    //this._serviceContainer.AddService(typeof(ILanguageManager), this._languageManager);
            //    //this._docTypeManager = new DocumentTypeManager(this._serviceContainer);
            //    //this._serviceContainer.AddService(typeof(IDocumentTypeManager), this._docTypeManager);
            //    //this._docManager = new DocumentManager(this._serviceContainer, (this.ApplicationType & ApplicationType.Debugger) != ApplicationType.Generic);
            //    //this._serviceContainer.AddService(typeof(IDocumentManager), this._docManager);
            //    //this._serviceContainer.AddService(typeof(IDesignerEventService), this._docManager);
            //    //this._toolboxService = new CToolboxService(this._serviceContainer);
            //    //this._serviceContainer.AddService(typeof(IToolboxService), this._toolboxService);
            //}
        }

        private void CloseApplication()
        {
            this._serviceContainer.RemoveService(typeof(IPreferencesService));
            if (this._prefService != null)
            {
                this._prefService.Save();
                ((IDisposable)this._prefService).Dispose();
                this._prefService = null;
            }
            ((IDisposable)this._exceptionHandler).Dispose();
            this._exceptionHandler = null;
            this._serviceContainer.RemoveService(typeof(IAsmApplicationIdentity));
            this._serviceContainer = null;
        }

        internal void RaiseStartupEvent()
        {
            if (this._startupHandler != null)
            {
                this._startupHandler(this, EventArgs.Empty);
            }
        }
        #endregion

        #region [=== PROPERTIES ==]
        private static AsmDependencyApplication instance;
        internal static AsmDependencyApplication Current {
            get { return instance; }
        }

        internal IServiceProvider ServiceProvider
        {
            get { return this._serviceContainer; }
        }
        #endregion

        #region [=== EVENTS HANDLERS ===]
        private object OnCreateService(IServiceContainer serviceContainer, System.Type type)
        {

            //if (type == typeof(IComponentGalleryService))
            //{
            //    if (this._componentGalleryService == null)
            //    {
            //        this._componentGalleryService = new ComponentGalleryService(this._serviceContainer);
            //    }
            //    return this._componentGalleryService;
            //}
            /*
            if (type == typeof(IWebBrowsingService))
            {
                if (this._webBrowsingService == null)
                {
                    this._webBrowsingService = new WebBrowsingService(this._serviceContainer);
                }
                return this._webBrowsingService;
            }*/
            /*
        if (type == typeof(IPrintService))
        {
                if (this._printService == null)
                {
                        //TODO: Activar Esto.
                        //this._printService = new PrintService(this._serviceContainer);
                }
                return this._printService;
        }*/
            /*
            if (type != typeof(IDataObjectMappingService))
            {
                return null;
            }
            if (this._dataObjectMappingService == null)
            {
                this._dataObjectMappingService = new DataObjectMappingService(this._serviceContainer);
            }
            return this._dataObjectMappingService;
            */
            return null;
        }

        private void OnApplicationWindowActivated(object sender, EventArgs e)
        {
            //if ((this.ApplicationType & ApplicationType.Workspace) != ApplicationType.Generic)
            //{
            //    //TODO: Activar Esto.
            //    //this._projectManager.Initialize();
            //}
        }

        private void OnApplicationWindowClosing(object sender, CancelEventArgs e)
        {
            //TODO: Activar Esto.
            /*
            if (((this.ApplicationType & ApplicationType.Workspace) != ApplicationType.Generic) && !this._projectManager.Close())
            {
                e.Cancel = true;
            }*/
        }
        #endregion

        #region [=== IServiceProvider ==]
        public object GetService(Type serviceType) {
            return this._serviceContainer.GetService(serviceType);
        }
        #endregion

        #region [=== IAsmApplicationIdentity ===]
        public event EventHandler Startup
        {
            add
            {
                this._startupHandler = (EventHandler)Delegate.Combine(this._startupHandler, value);
            }
            remove
            {
                if (this._startupHandler != null)
                {
                    this._startupHandler = (EventHandler)Delegate.Remove(this._startupHandler, value);
                }
            }
        }

        public string GetSetting(string settingName)
        {
            return ((IAsmApplicationIdentity)this).GetSetting(settingName, true);
        }

        public string GetSetting(string settingName, bool allowCommandLineOverride)
        {
            if ((settingName == null) || (settingName.Length == 0))
            {
                throw new ArgumentNullException("settingName");
            }
            string str = null;
            if (allowCommandLineOverride)
            {
                str = (string)this._commandLine.Options[settingName];
                if (str != null)
                {
                    return str;
                }
            }
            if (this._prefService != null)
            {
                str = ((IPreferencesService)this._prefService).GetPreferencesStore(typeof(IAsmApplicationIdentity)).GetValue(settingName, (string)null);
                if (str != null)
                {
                    return str;
                }
            }
            return ConfigurationSettings.AppSettings[settingName];
        }

        public bool OnUnhandledException(Exception e)
        {
            return this.OnUnhandledException(e);
        }

        public void SetSetting(string settingName, string settingValue)
        {
            if ((settingName == null) || (settingName.Length == 0))
            {
                throw new ArgumentNullException("settingName");
            }
            if (this._prefService != null)
            {
                CPreferencesStore preferencesStore = ((IPreferencesService)this._prefService).GetPreferencesStore(typeof(IAsmApplicationIdentity));
                if ((settingValue == null) || (settingValue.Length == 0))
                {
                    preferencesStore.ClearValue(settingName);
                }
                else
                {
                    preferencesStore.SetValue(settingName, settingValue, string.Empty);
                }
            }
        }

        public void ShowHelpTopics()
        {
            throw new NotImplementedException();
        }

        public string ApplicationPath
        {
            get { return Path.GetDirectoryName(base.GetType().Module.FullyQualifiedName); }
        }

        public string ApplicationPrivatePath
        {
            get { return Path.Combine(this.ApplicationPath, this.Name); }
        }

        public Utility.CCommandLine CommandLine
        {
            get { return this._commandLine; }
        }

        public string ComponentsPath
        {
            get { return string.Empty; }
        }

        public string Name
        {
            get { return base.GetType().Assembly.GetName().Name; }
        }

        public virtual string PluginsPath
        {
            get { return string.Empty; }
        }

        public virtual string PreferencesFileName { get { return string.Empty; } }

        public string TemplatesPath
        {
            get { return string.Empty; }
        }

        public virtual string Title { get { return string.Empty; } }

        public System.Collections.IDictionary WebLinks {
            get {
                if (!this._webLinksLoaded) {
                    if (this._webLinks == null) {
                        //TODO: Cambiar esto
                        this._webLinks = (IDictionary)ConfigurationSettings.GetConfig("microsoft.matrix/webLinks");
                    }
                    this._webLinksLoaded = true;
                }
                return this._webLinks;
            }
        }
        #endregion
    }
}
